#include "err.hpp"
#include "sock.hpp"
#include <string>
#include <cstring>
#include <functional>
#define arrsock_num 1024

namespace zxf
{

    class Select_server
    {

    public:
        using func_t = std::function<std::string(std::string &)>;
        Select_server(uint16_t port) : _port(port), _listensock(-1)
        {
        }
        ~Select_server()
        {
            if (_listensock >= 0)
            {
                close(_listensock);
            }
            if (_arrsock)
            {
                delete[] _arrsock;
            }
        }
        void initarrsock()
        {
            for (int i = 0; i < arrsock_num; i++)
            {
                _arrsock[i] = -1;
            }
            logMessage(NORMAL, "initarrsock success !!!");
        }
        void initServer()
        {
            _listensock = Sock::Socket();
            Sock::Bind(_listensock, _port);
            Sock::Listen(_listensock);
            _arrsock = new int[arrsock_num];
            initarrsock();
            _arrsock[0] = _listensock;
        }

        void ListenHeader()
        {
            int fd = Sock::Accept(_listensock, nullptr, nullptr);
            for (int i = 0; i < arrsock_num; i++)
            {
                if (i == arrsock_num)
                {
                    logMessage(WARNING, " select full !!!");
                    break;
                }
                if (_arrsock[i] == -1)
                {
                    _arrsock[i] = fd;
                    break;
                }
            }
        }
        void CommonHeader(int fd, int pos)
        {
            logMessage(DEBUG, "CommonHeader in !!");
            char buf[1024];
            int ret = recv(fd, buf, 1023, 0);
            if (ret < 0)
            {
                // 读取出错了
                close(fd);
                _arrsock[pos] = -1;
                logMessage(ERROR, "recv err : %s", strerror(errno));
                return;
            }
            else if (ret == 0)
            {
                // 客户端退出
                close(fd);
                _arrsock[pos] = -1;
                logMessage(NORMAL, "client quit");
                return;
            }
            else
            {
                buf[ret] = 0;
                std::string request = buf;
                std::cout << "读取到: " << request << std::endl;
                const std::string response = _func(request);
                write(fd, response.c_str(), response.size());
            }
        }

        void Eventheader(fd_set rfds)
        {
            for (int i = 0; i < arrsock_num; i++)
            {
                if (_arrsock[i] == -1)
                {
                    continue;
                }
                if (_arrsock[i] == _listensock && FD_ISSET(_arrsock[i], &rfds))
                {
                    ListenHeader();
                }
                if (_arrsock[i] != _listensock && FD_ISSET(_arrsock[i], &rfds))
                {
                    CommonHeader(_arrsock[i], i);
                }
            }
        }
        void start(func_t func)
        {
            _func = func;

            for (;;)
            {
                // std::string ip = "";
                // uint16_t port = 0;
                // Sock::Accept(_listensock, &ip, &port);
                // std::cout<<"ip: "<<ip <<"   "<<"port: "<<port<<std::endl;
                // 现在我们要把 所有的sock都托管给 select 监管.然后收到消息之后我们进行处理

                // 创建一个读fd集合
                fd_set read_fds;
                // 初始化为空
                FD_ZERO(&read_fds);
                // 将_listensock添加进去
                // FD_SET(_listensock, &read_fds);
                // 将arrsock添加进去
                int max_fd = _listensock;
                for (int i = 0; i < arrsock_num; i++)
                {
                    if (_arrsock[i] != -1)
                    {
                        FD_SET(_arrsock[i], &read_fds);
                        if(max_fd < _arrsock[i])
                        {
                            max_fd = _arrsock[i];
                        }
                    }
                }

                struct timeval wait_time = {2, 0};
                int ret = select(max_fd + 1, &read_fds, nullptr, nullptr, &wait_time);
                // 注意read_fds是一个输入输出型的参数,输入要关心的文件描述符, 输出就绪的文件描述符.
                if (ret == -1)
                {
                    // err
                    logMessage(FATAL, "select err !! errno: %d  err: %s", errno, strerror(errno));
                    exit(SELECT_ERR);
                }
                else if (ret == 0)
                {
                    logMessage(NORMAL, "timeout !!! ");
                    continue;
                }
                else
                {
                    // 有文件描述符就绪了
                    logMessage(NORMAL, "have event ready!");
                    Eventheader(read_fds);
                }
            }
        }

    private:
        uint16_t _port;
        int _listensock;
        int *_arrsock; // 所有要关心的fd
        func_t _func;
    };

}